home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
smaltalk
/
manchest.lha
/
MANCHESTER
/
manchester
/
2.2
/
structure-copying.st
< prev
next >
Wrap
Text File
|
1993-07-24
|
18KB
|
619 lines
" NAME structure-copying
AUTHOR neild@cs.man.ac.uk
FUNCTION see StructureInputTable.2.3fix
ST-VERSIONS
PREREQUISITES
CONFLICTS
DISTRIBUTION world
VERSION 1.1
DATE 22 Jan 1989
SUMMARY structure-copying
For moving Smalltalk structures between
images. This version does not work properly with 2.3 images.
To get these working file this in then file in
StructureInputTable.2.3fix.st. Neil Dyer
"!
'From Smalltalk-80, Version 2.2 of July 4, 1987 on 23 August 1988 at 5:27:06 pm'!
!ArrayedCollection methodsFor: 'structure copying'!
readStructureFrom: aStream structureTable: structureTable
"Read my innards from aStream. Reads in binary format if possible."
(self class isBits and: [aStream isFileStream])
ifTrue:
[aStream binary; next: self basicSize into: self; text; skip: 3]
ifFalse:
[super readStructureFrom: aStream structureTable: structureTable]!
storeDefinitionOn: aStream structureTable: structureTable
"Stores the contents of an object. Stores in binary format if possible."
(self class isBits and: [aStream isFileStream])
ifTrue:
[self basicSize printOn: aStream.
aStream space; binary; nextPutAll: self; text; space]
ifFalse:
[super storeDefinitionOn: aStream structureTable: structureTable]! !
!Boolean methodsFor: 'structure copying'!
isUniqueValue
^true! !
!Character methodsFor: 'structure copying'!
storeStructureOn: aStream structureTable: structureTable
"Stores the definition of a SmallInteger aStream. This is just its
printString.
This scheme is closely based upon Steve Vegdahl's work presented in
Moving Structures between Smalltalk Images, OOPSLA '86"
structureTable putIdOf: self on: aStream ifNew: [self printOn: aStream]! !
!Float methodsFor: 'structure copying'!
storeStructureOn: aStream structureTable: structureTable
"Stores the definition of a Float on aStream. This is just its printString.
This scheme is closely based upon Steve Vegdahl's work presented in
Moving Structures between Smalltalk Images, OOPSLA '86"
structureTable
putIdOf: self
on: aStream
ifNew:
[aStream nextPut: $F.
self printOn: aStream]! !
!Object methodsFor: 'As yet unclassified'!
storeStructure
"Writes a description of the receiver into a file, in a way that allows
the object's structure to be reconstructed from the file's contents.
Returns the file's name"
| fileName file |
fileName _ (FileDirectory named: '')
requestFileName: 'Structure file name?'
default: (self class name, '.', self asOop printString, '.structure')
version: #any
ifFail: [].
^fileName ~~ nil
ifTrue:
[
file _ FileStream fileNamed: (fileName ).
Cursor write showWhile: [self storeStructureOn: file].
file close.
fileName]! !
!Object methodsFor: 'public structure copying'!
storeStructureOn: aStream
"Writes a description of the receiver onto aStream, in a way that allows
the object's structure to be reconstructed from the stream's contents"
StructureOutputTable storeStructureOf: self on: aStream! !
!Object methodsFor: 'structure copying'!
basicDependents
"Answer an OrderedCollection of the objects that are dependent on the
receiver, or nil if none. This is for faster dependency access in structure
copying"
^DependentsFields at: self ifAbsent: []!
globalExpression
"If I am a 'global', i.e. am known on another system (e.g. Form black), return an
expression naming me in a string. Return nil if none"
^nil!
isUniqueValue
^false!
readStructureFrom: aStream structureTable: structureTable
"Read my innards from aStream"
| index |
1 to: self basicSize do: [:i|
self basicAt: i put: structureTable nextObject].
index _ 0.
[aStream peek ~~ $)]
whileTrue:
[self instVarAt: (index _ index + 1) put: structureTable nextObject].
aStream skip: 2!
storeDefinitionOn: aStream structureTable: structureTable
"Stores the contents of an object. First the number of variable fields or -
if none, then the object's instance variables, followed by its indexed variables."
self class isVariable
ifTrue:
[self basicSize printOn: aStream.
1 to: self basicSize do: [:i|
aStream space.
(self basicAt: i)
storeStructureOn: aStream
structureTable: structureTable]]
ifFalse: [aStream nextPut: $-].
1 to: self class instSize do: [:i|
aStream space.
(self instVarAt: i) storeStructureOn: aStream structureTable: structureTable].
aStream space!
storeStructureOn: aStream structureTable: structureTable
"Stores the definition of an object onto aStream, given that the objects
in structureTable have already been seen. This method is rarely overridden.
The object's id number is written out followed by a letter identifying its form
of definition and its class name, followed by a pair of parentheses enclosing
its definition.
This scheme is closely based upon Steve Vegdahl's work presented in
Moving Structures between Smalltalk Images, OOPSLA '86"
structureTable
putIdOf: self
on: aStream
ifNew: [
self isUniqueValue
ifTrue: [aStream nextPut: $U; nextPutAll: self class name.
^self].
structureTable if: self isGlobal: [:expr|
aStream nextPutAll: 'G<'; nextPutAll: expr; nextPut: $>.
^self].
aStream nextPut: $C; nextPutAll: self class name; nextPut: $(.
self storeDefinitionOn: aStream structureTable: structureTable.
aStream nextPut: $)]! !
!Set methodsFor: 'structure copying'!
readStructureFrom: aStream structureTable: structureTable
super readStructureFrom: aStream structureTable: structureTable.
self rehash! !
!SmallInteger methodsFor: 'structure copying'!
storeStructureOn: aStream structureTable: structureTable
"Stores the definition of a SmallInteger aStream. This is just its
printString.
This scheme is closely based upon Steve Vegdahl's work presented in
Moving Structures between Smalltalk Images, OOPSLA '86"
aStream nextPut: $0.
self printOn: aStream! !
!String methodsFor: 'structure copying'!
storeStructureOn: aStream structureTable: structureTable
"Stores the definition of a String onto aStream.
An extra space is appended to stream to fix a problem with String>>readFrom:.
This scheme is closely based upon Steve Vegdahl's work presented in
Moving Structures between Smalltalk Images, OOPSLA '86"
structureTable
putIdOf: self
on: aStream
ifNew: [self storeOn: aStream]! !
IdentityDictionary variableSubclass: #StructureInputTable
instanceVariableNames: 'stream currentId typeTable '
classVariableNames: 'TypeTable '
poolDictionaries: ''
category: 'System-Support'!
StructureInputTable comment:
'StructureInputTable reads from a stream containing a structure produced by Object>storeStructure:on:.
The syntax is:
<Structure> :- <IntegerDefinition> | <ObjectId> <ObjectDefinition>
<IntegerDefinition> :- 0 <integer>
<ObjectId> :- <integer>
<ObjectDefinition> :- G < <expression> > |
C <ClassName> <ObjectStructure> |
F <float> |
$ <character> |
# '' <symbol> '' |
'' <string> ''
<ObjectStructure> :- ( <Size> <Contents> )
<Size> :- - | <number>
<Contents> :- <ObjectId> <ObjectReference> <Contents> |
<>
<ObjectReference> :- <ObjectDefinition> |
<>'!
!StructureInputTable methodsFor: 'initialize-release'!
initialize
"The typeTable is kept in an instance variable to facilitate subclassing"
typeTable _ TypeTable! !
!StructureInputTable methodsFor: 'public access'!
readFrom: aStream
| object |
stream _ aStream.
object _ self nextObject.
self readDependencies.
^object! !
!StructureInputTable methodsFor: 'structure reading'!
readCharacter
| character |
stream next.
character _ stream next.
stream next ~= $ ifTrue: [self syntaxError].
self at: currentId put: character.
^character!
readFloat
| float |
stream next.
float _ self at: currentId put: (Float readFrom: stream).
stream next ~= $ ifTrue: [self syntaxError].
^float!
readGlobal
| global |
stream next; next.
global _ self at: currentId put: (Compiler evaluate: self globalExpression).
stream next ~= $ ifTrue: [self syntaxError].
^global!
readString
^self at: currentId put: (String readFrom: stream)!
readSymbol
stream next.
^self at: currentId put: (String readFrom: stream) asSymbol!
readUniqueValueDefinition
stream next.
^self at: currentId put: (Smalltalk at: (stream upTo: $ ) asSymbol) someInstance! !
!StructureInputTable methodsFor: 'As yet unclassified'!
readClassAndDefinition
| obj class varCount |
Cursor execute showWhile: [
stream next.
class _ Smalltalk at: (stream upTo: $() asSymbol.
obj _ (stream peek = $-
ifTrue: [stream skip: 1. class basicNew]
ifFalse: [varCount _ Integer readFrom: stream radix: 10.
varCount == 0 ifTrue: [class basicNew]
ifFalse: [class basicNew: varCount]]).
stream skip: 1.
self at: currentId put: obj].
obj readStructureFrom: stream structureTable: self.
^obj!
readDependencies
| obj |
"format: $D <objid> $( [ $ <depId> ]* $) "
[stream peek == $D]
whileTrue: [
stream skip: 1. "skip $D"
obj _ self at: (Integer readFrom: stream).
stream skip: 1. "skip ( "
[stream next ~~ $)]
whileTrue: [
obj addDependent: (self at: (Integer readFrom: stream))]]! !
!StructureInputTable methodsFor: 'adding'!
grow
"Must copy instance variables when growing"
| theStream theId theTypeTable |
theStream _ stream. theId _ currentId. theTypeTable _ typeTable.
super grow. "does the grow & become"
stream _ theStream. currentId _ theId. typeTable _ theTypeTable! !
!StructureInputTable methodsFor: 'private'!
findKeyOrNil: key
"My keys are integers. Use their values for their hash, rather than their oop."
| index length probe pass |
length _ self basicSize.
pass _ 1.
index _ key \\ length + 1.
[(probe _ self basicAt: index) == nil or: [probe == key]]
whileFalse: [(index _ index + 1) > length
ifTrue:
[index _ 1.
pass _ pass + 1.
pass > 2 ifTrue: [^self grow findKeyOrNil: key]]].
^index!
globalExpression
| aStream char |
aStream _ WriteStream on: (String new: 16).
[(char _ stream next) ~~ $>]
whileTrue:
[aStream nextPut: char].
^aStream contents!
nextObject
"Read the Object Id then the definition"
^self perform: (typeTable at: stream peek asciiValue)!
readId
"This is called from nextObject. Read the Object ID then the definition."
| char |
currentId _ Integer readFrom: stream radix: 10.
^((char _ stream peek) == $ or: [char == $)])
ifTrue: [stream skip: 1. self at: currentId]
ifFalse: [self perform: (typeTable at: char asciiValue)]!
readInteger
"This is called from nextObject. There is no Object Id. Read the definition."
| integer |
stream next.
integer _ Integer readFrom: stream.
stream next ~= $ ifTrue: [self syntaxError].
^integer!
rehash
"Must copy instance variables when rehashing"
| theStream theId theTypeTable |
theStream _ stream. theId _ currentId. theTypeTable _ typeTable.
super rehash. "does the rehash & become"
stream _ theStream. currentId _ theId. typeTable _ theTypeTable!
syntaxError
self error: 'syntax error: space expected'! !
"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
StructureInputTable class
instanceVariableNames: ''!
!StructureInputTable class methodsFor: 'class initialization'!
initialize
"StructureInputTable initialize"
TypeTable _ Array new: 256.
"Token start characters"
TypeTable at: $0 asciiValue put: #readInteger.
$1 asciiValue to: $9 asciiValue do: [:ascii| TypeTable at: ascii put: #readId].
"Definition type start characters"
TypeTable
at: $G asciiValue put: #readGlobal;
at: $U asciiValue put: #readUniqueValueDefinition;
at: $C asciiValue put: #readClassAndDefinition;
at: $F asciiValue put: #readFloat;
at: $$ asciiValue put: #readCharacter;
at: $# asciiValue put: #readSymbol;
at: $' asciiValue put: #readString! !
!StructureInputTable class methodsFor: 'instance creation'!
new: anInteger
^(super new: anInteger) initialize! !
!StructureInputTable class methodsFor: 'structure reading'!
readFrom: streamOrFileName
"Reads an object's structure from the stream streamOrFileName
or the file named streamOrFileName"
(streamOrFileName isKindOf: String)
ifTrue:
[^Cursor read showWhile: [(self new: 1024) readFrom: (FileStream fileNamed: streamOrFileName)]].
^(self new: 1024) readFrom: streamOrFileName! !
StructureInputTable initialize!
IdentityDictionary variableSubclass: #StructureOutputTable
instanceVariableNames: 'idCount idOfNil globalDictionaries globals '
classVariableNames: 'GlobalDictionaries Globals '
poolDictionaries: ''
category: 'System-Support'!
!StructureOutputTable methodsFor: 'initialize-release'!
initialize
"You should change this method to add whatever objects you consider
constant across systems, and remove any objects you don't consider
constant. Also, you can implement globalExpression for specific classes."
globals _ Globals.
globalDictionaries _ GlobalDictionaries.
idCount _ 0! !
!StructureOutputTable methodsFor: 'As yet unclassified'!
appendDependenciesTo: aStream
|dependents noDependents depId|
"Add dependency information to aStream.
The structure has been stored on aStream, thus the table
contains all objects
other than SmallIntegers contained in the structure. We add
only the dependencies
between objects in the structure and we miss dependencies
of SmallIntegers"
self keysDo: [:obj |
(dependents _ obj basicDependents) ~~ nil
ifTrue: [
noDependents _ true.
dependents do: [:dep |
(depId _ self at: dep ifAbsent: []) ~~ nil
ifTrue: [
noDependents
ifTrue: [
aStream space; nextPut: $D.
(self at: obj) printOn: aStream base: 10.
aStream nextPut: $(.
noDependents _ false].
aStream space.
depId printOn: aStream base: 10]].
noDependents ifFalse: [aStream nextPut: $)]]]!
putIdOf: anObject on: aStream ifNew: aBlock
| cursor |
(self at: anObject ifAbsent: [
cursor _ Sensor currentCursor.
Cursor execute show.
anObject == nil
ifTrue: [
idOfNil == nil
ifTrue: [
(idOfNil _ (idCount _ idCount + 1)) printOn: aStream base: 10.
cursor show.
^aBlock value].
cursor show.
idOfNil]
ifFalse: [
(self at: anObject put: (idCount _ idCount + 1)) printOn: aStream base: 10.
cursor show.
^aBlock value]])
printOn: aStream! !
!StructureOutputTable methodsFor: 'testing'!
if: anObject isGlobal: aBlock
| globalExpression |
(globalExpression _ anObject globalExpression) ~~ nil
ifTrue: [^aBlock value: globalExpression].
(globalExpression _ globals at: anObject ifAbsent: []) ~~ nil
ifTrue: [^aBlock value: globalExpression].
globalDictionaries do: [:dict|
dict associationsDo: [:assoc|
assoc value == anObject
ifTrue: [^aBlock value: (Smalltalk keyAtValue: dict), ' at: ', assoc key storeString]]]! !
!StructureOutputTable methodsFor: 'adding'!
grow
"Must copy instance variables when growing"
| theIdCount theIdOfNil theGlobalDictionaries theGlobals |
theIdCount _ idCount. theIdOfNil _ idOfNil. theGlobals _ globals.
theGlobalDictionaries _ globalDictionaries.
super grow. "does the grow & become"
idCount _ theIdCount. idOfNil _ theIdOfNil. globals _ theGlobals.
globalDictionaries _ theGlobalDictionaries! !
!StructureOutputTable methodsFor: 'private'!
rehash
"Must copy instance variables when rehashing"
| theIdCount theIdOfNil theGlobalDictionaries theGlobals |
theIdCount _ idCount. theIdOfNil _ idOfNil. theGlobals _ globals.
theGlobalDictionaries _ globalDictionaries.
super rehash. "does the rehash & become"
idCount _ theIdCount. idOfNil _ theIdOfNil. globals _ theGlobals.
globalDictionaries _ theGlobalDictionaries! !
"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
StructureOutputTable class
instanceVariableNames: ''!
!StructureOutputTable class methodsFor: 'As yet unclassified'!
initialize
|object|
"Collect the objects considered `global' i.e. shared between systems.
You should change this method to add whatever objects you consider
constant across systems, and remove any objects you don't consider
constant. Also, look at the instance method initialize for further customization."
"StructureOutputTable initialize"
Globals _ IdentityDictionary new: 64.
GlobalDictionaries _ IdentityDictionary new: 16.
"Provisionally assume all objects in Smalltalk except processes, and all objects
in all dictionaries in Smalltalk except Undeclared (typically pools) are `global'"
Smalltalk associationsDo: [:assoc|
(((object _ assoc value) isKindOf: Behavior) or: [object isKindOf: Process])
ifFalse:
[Globals at: object put: assoc key.
(object ~~ Smalltalk and: [(object isKindOf: Dictionary) and: [object ~~ Undeclared]])
ifTrue:
[GlobalDictionaries add: assoc]]].
"Provisionally assume the default fonts & Form masks are `global'"
1 to: TextStyle default fontArray size do: [:fontIndex|
Globals
at: (TextStyle default fontAt: fontIndex)
put: 'TextStyle default fontAt: ', fontIndex printString].
#( white veryLightGray lightGray gray darkGray black ) do: [:maskName|
Globals
at: (Form perform: maskName)
put: 'Form ', maskName]! !
!StructureOutputTable class methodsFor: 'structure copying'!
storeStructureOf: anObject on: aStream
| table |
table _ (self new: 1024) initialize.
anObject storeStructureOn: aStream structureTable: table.
table appendDependenciesTo: aStream! !
StructureOutputTable initialize!
!Symbol methodsFor: 'structure copying'!
storeStructureOn: aStream structureTable: structureTable
"Stores the definition of a Symbol onto aStream.
An extra space is appended to stream to fix a problem with String>>readFrom:.
This scheme is closely based upon Steve Vegdahl's work presented in
Moving Structures between Smalltalk Images, OOPSLA '86"
structureTable
putIdOf: self
on: aStream
ifNew: [aStream nextPut: $#. super storeOn: aStream]! !
!UndefinedObject methodsFor: 'structure copying'!
isUniqueValue
^true! !